import styles from './index.less'
import { Dropdown, Tabs, message } from "antd";
import type { MenuInfo } from 'rc-menu/lib/interface';
import { useMemo, useState, ReactNode, useEffect, HTMLAttributes, CSSProperties, cloneElement, ReactElement } from "react";
import type { Items, KeepElementsType, MenuClickStrateg, layoutTabs } from './typings.d'
import { OperationType } from './typings.d'
import { history, useAppData, useModel } from '@umijs/max'
import { getKeepAlive, menuItemRender, sortCurrentByItemsKeys } from './utils';
import type { DragEndEvent } from '@dnd-kit/core';
import { DndContext, PointerSensor, useSensor } from '@dnd-kit/core';
import {
    arrayMove,
    horizontalListSortingStrategy,
    SortableContext,
    useSortable,
} from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';

interface DraggableTabPaneProps extends HTMLAttributes<HTMLDivElement> {
    'data-node-key': string;
}

const DraggableTabNode = ({ ...props }: DraggableTabPaneProps) => {
    const { attributes, listeners, setNodeRef, transform, transition } = useSortable({
        id: props['data-node-key'],
    });

    const style: CSSProperties = {
        ...props.style,
        transform: CSS.Transform.toString(transform && { ...transform, scaleX: 1 }),
        transition,
        cursor: 'move',
    };

    return cloneElement(props.children as ReactElement, {
        ref: setNodeRef,
        style,
        ...attributes,
        ...listeners,
    });
};

const Tab = (props: layoutTabs) => {

    const {
        keepElements,
        navigate,
        dropByCacheKey,
        activeKey,
        refreshTab,
        dropLeftTabs,
        dropRightTabs,
        dropOtherTabs
    } = props
    const { setTabInstance } = useModel('useCustomTabs', (model) => ({
        setTabInstance: model.setTabInstance,
    }));
    useEffect(() => {
        // 修正缓存参数指向
        const { pathname, search } = history.location
        if (keepElements?.current?.[pathname]) {
            keepElements.current[pathname].location.search = search
        }
    }, [history.location]);

    useEffect(() => {
        setTabInstance(props)
    }, [props])
    const [items, setItems] = useState<Items[]>([])

    const sensor = useSensor(PointerSensor, { activationConstraint: { distance: 10 } });

    const onDragEnd = ({ active, over }: DragEndEvent) => {
        if (active.id !== over?.id) {
            const activeIndex = items.findIndex((i) => i.key === active.id);
            const overIndex = items.findIndex((i) => i.key === over?.id);
            const moveList: Items[] = arrayMove(items, activeIndex, overIndex)
            setItems(moveList)
            sortCurrentByItemsKeys(keepElements, moveList)
        }
    };

    const [menuItemList, setMenuItemList] = useState<any[]>([]);
    const [currentPath, setCurrentPath] = useState<string>('');
    const routerList: KeepElementsType[] = Object.values(keepElements?.current || {})
    const pathList: string[] = Object.keys(keepElements?.current || {})
    const length: number = routerList?.length ?? 0//获取长度
    const { routes } = useAppData() as any;

    const onEdit = (targetKey: string) => {
        if (pathList.length === 1) {
            message.info('至少要保留一个窗口')
            return
        }
        dropByCacheKey(targetKey)
        if (targetKey === activeKey) {
            // 删除当前选中的tab时:
            // 1.如果当前tab是第一个时自动选中后一个
            // 2.不是第一个时自动选中前一个
            const i = pathList.indexOf(targetKey)
            navigate(pathList[i === 0 ? i + 1 : i - 1])
        }
    }

    // 右键下拉处理
    const menuClickStrateg: MenuClickStrateg = {
        [OperationType.REFRESH]: () => refreshTab(currentPath),//刷新
        [OperationType.CLOSECRUTTNET]: () => onEdit(currentPath),//关闭当前
        [OperationType.CLOSEOTHER]: () => dropOtherTabs(currentPath),//关闭其他
        [OperationType.CLOSELEFT]: () => dropLeftTabs(currentPath),//关闭左侧
        [OperationType.CLOSERIGHT]: () => dropRightTabs(currentPath),//关闭右侧
    }

    const renderLabel = (icon: ReactNode, name: string, pathname: string) => <Dropdown
        menu={{
            items: menuItemList, onClick: ({ key, domEvent }: MenuInfo) => {
                domEvent.stopPropagation();
                if (key !== OperationType.CLOSECRUTTNET) {
                    navigate(currentPath)
                }
                menuClickStrateg?.[key]?.()
            }
        }}
        onOpenChange={(open: boolean) => {
            if (!open) return
            setCurrentPath(pathname)
            // 当前下标
            const currentIndex: number = keepElements.current?.[pathname]?.index
            // 左菜单显示标识
            const leftShow: boolean = length > 1 && !!currentIndex
            // 右菜单显示标识
            const rightShow: boolean = length > 1 && currentIndex !== (routerList.length - 1)
            setMenuItemList(menuItemRender(length, leftShow, rightShow))
        }}
        trigger={['contextMenu']}
    >
        <div>{icon}{name}</div>
    </Dropdown >

    useEffect(() => {
        setItems(routerList.map(({ icon, name, location: { pathname } }: KeepElementsType) => ({
            key: pathname,
            label: renderLabel(icon, name, pathname),
            closable: length > 1,
        })))
    }, [props, menuItemList])
    // 获取当前keepAlive = false 的路由路径
    const keepAliveList: string[] = useMemo(() => getKeepAlive(routes), [])
    console.log('keepElements?.current', keepElements?.current);
    return (
        <Tabs
            style={{ zIndex: 99 }}
            items={items}
            hideAdd
            renderTabBar={(tabBarProps, DefaultTabBar) => (
                <DndContext sensors={[sensor]} onDragEnd={onDragEnd}>
                    <SortableContext items={items.map((i) => i.key)} strategy={horizontalListSortingStrategy}>
                        <DefaultTabBar {...tabBarProps}>
                            {(node) => (
                                <DraggableTabNode {...node.props} key={node.key}>
                                    {node}
                                </DraggableTabNode>
                            )}
                        </DefaultTabBar>
                    </SortableContext>
                </DndContext>
            )}
            onChange={(key: string) => {
                const keepPathMap: Record<string, KeepElementsType> = keepElements?.current
                console.log('keepPathMap', keepPathMap);
                // 路由keepAlive不为true 时刷新组件
                if (!keepAliveList.includes(key)) {
                    //如果每个组件都需要刷新，这个判断去掉
                    refreshTab(key)
                }
                // 修正跳转参数
                const { pathname, search } = keepPathMap?.[key].location
                navigate(pathname + search);
            }}
            activeKey={activeKey}
            type="editable-card"
            onEdit={(targetKey: string | any) => onEdit(targetKey)}
        />
    )
}

const customTabs = () => ((props: layoutTabs) => {
    const { isKeep } = props
    return (
        <div className={styles.tabsLayout} hidden={!isKeep}>
            <Tab {...props} />
        </div>
    )
})

export default customTabs